package com.zzzy.sys.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzzy.common.util.AssertUtil;
import com.zzzy.common.util.CglibBeanCopierUtil;
import com.zzzy.common.vo.PageResult;
import com.zzzy.framework.common.constant.AdminUserConstant;
import com.zzzy.framework.common.enums.sys.UserStatusEnum;
import com.zzzy.framework.common.util.SecurityUtils;
import com.zzzy.framework.core.mybatis.query.MPJLambdaWrapperE;
import com.zzzy.framework.dto.LoginUser;
import com.zzzy.sys.api.UserApi;
import com.zzzy.sys.common.constant.PasswordRegConstant;
import com.zzzy.sys.dao.entity.Dept;
import com.zzzy.sys.dao.entity.User;
import com.zzzy.sys.dao.mapper.UserMapper;
import com.zzzy.sys.dto.UserInfoDto;
import com.zzzy.sys.vo.UserSelectPageReq;
import com.zzzy.sys.vo.profile.UserProfileUpdateReq;
import com.zzzy.sys.vo.profile.UserUpdatePasswordReq;
import com.zzzy.sys.vo.user.UserInfoRes;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author fc
 * @since 2024-04-19
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> implements UserApi {

    @Resource
    protected DeptService deptService;

    public User getUserById(Long id) {
        User user = baseMapper.selectById(id);
        AssertUtil.nonNull(user, "用户不存在");
        return user;
    }

    public User getSimpleUserById(Long id) {
        User user = getUserById(id);
        user.setPassword(null);
        return user;
    }
    protected User getUserByUsername(String username) {
        return baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
    }

    public UserInfoRes getLoginUserInfo() {
        User user = getSimpleUserById(SecurityUtils.getLoginUser().getId());
        UserInfoRes userInfoRes = CglibBeanCopierUtil.copy(user, UserInfoRes.class);
        if (Objects.nonNull(user.getDeptId())){
            Dept dept = deptService.getDeptById(user.getDeptId());
            userInfoRes.setDeptName(dept.getName());
        }
        return userInfoRes;
    }

    public void updateLoginUserInfo(UserProfileUpdateReq updateReq) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        User user = getUserById(loginUser.getId());
        CglibBeanCopierUtil.copy(updateReq, user);
        CglibBeanCopierUtil.copy(updateReq, loginUser);
        user.setUpdateTime(LocalDateTime.now());
        updateById(user);
    }

    public void updateLoginUserPassword(UserUpdatePasswordReq updatePasswordReq) {
        AssertUtil.isEquals(updatePasswordReq.getNewPassword(), updatePasswordReq.getSureNewPassword(), "新密码与确认密码不一致");
        AssertUtil.isTrue(SecurityUtils.matchesPassword(updatePasswordReq.getOldPassword(), SecurityUtils.getLoginUser().getPassword()), "原密码错误");
        checkPasswordPatten(updatePasswordReq.getNewPassword());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        User user = getUserById(loginUser.getId());
        String encryptPassword = SecurityUtils.encryptPassword(updatePasswordReq.getNewPassword());
        loginUser.setPassword(encryptPassword);
        user.setPassword(encryptPassword);
        user.setUpdateTime(LocalDateTime.now());
        updateById(user);
    }

    private void checkPasswordPatten(String password){
        AssertUtil.isTrue(Pattern.matches(PasswordRegConstant.PASSWORD_REG, password), "请输入6-20位的数字、字母和特殊字符 ~_!@#$%^&*+|?- 的组合作为新密码");
    }
    public List<User> getUserListByDeptId(Long deptId) {
        MPJLambdaWrapperE<User> queryWrapperE = new MPJLambdaWrapperE<>();
        queryWrapperE.select(User::getId, User::getUsername, User::getNickName, User::getDuty, User::getSex, User::getStatus
                , User::getPhoneNumber, User::getEmail, User::getUpdateTime, User::getCreateTime);
        queryWrapperE.selectAs(Dept::getName, User::getDeptName);

        queryWrapperE.leftJoin(Dept.class, Dept::getId, User::getDeptId);
        queryWrapperE.eq(Dept::getId, deptId);

        queryWrapperE.orderByDesc(User::getId);
        return baseMapper.selectJoinList(User.class, queryWrapperE);
    }

    /**
     * 通过父部门ID查询指定部门及子部门下所有用户
     */
    public List<User> getDeptAndChildDeptUserListByParentDeptId(Long deptId) {
        return baseMapper.selectDeptAndChildDeptUserListByParentDeptId(deptId);
    }

    @Override
    public UserInfoDto getUserInfoById(Long userId) {
        User user = getSimpleUserById(userId);
        UserInfoRes userInfoRes = CglibBeanCopierUtil.copy(user, UserInfoRes.class);
        if (Objects.nonNull(user.getDeptId())){
            Dept dept = deptService.getDeptById(user.getDeptId());
            userInfoRes.setDeptName(dept.getName());
        }
        return CglibBeanCopierUtil.copy(userInfoRes, UserInfoDto.class);
    }

    @Override
    public List<UserInfoDto> getUserInfoListByDeptId(Long... deptIds) {
        List<Long> deptIdList = Arrays.asList(deptIds);
        if (CollectionUtils.isEmpty(deptIdList)){
            return Collections.EMPTY_LIST;
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(User::getId, User::getUsername, User::getNickName, User::getDeptId, User::getDuty, User::getSex, User::getStatus
                , User::getPhoneNumber, User::getEmail, User::getUpdateTime, User::getCreateTime);
        queryWrapper.in(User::getDeptId, deptIdList).eq(User::getStatus, UserStatusEnum.ENABLE.getValue());
        return baseMapper.selectList(queryWrapper).stream()
                .map(user -> CglibBeanCopierUtil.copy(user, UserInfoDto.class)).collect(Collectors.toList());
    }

    @Override
    public PageResult<UserInfoDto> userSelectPage(UserSelectPageReq queryReq) {
        MPJLambdaWrapperE<User> queryWrapperE = new MPJLambdaWrapperE<>();
        queryWrapperE.select(User::getId, User::getUsername, User::getNickName, User::getDuty, User::getSex, User::getStatus
                , User::getPhoneNumber, User::getEmail, User::getUpdateTime, User::getCreateTime);
        queryWrapperE.selectAs(Dept::getName, User::getDeptName);

        queryWrapperE.leftJoin(Dept.class, Dept::getId, User::getDeptId)
                .likeIfExists(Dept::getName, queryReq.getDeptName());

        queryWrapperE.likeIfPresent(User::getNickName, queryReq.getNickName())
                .likeIfPresent(User::getPhoneNumber, queryReq.getPhoneNumber())
                .eqIfPresent(User::getStatus, UserStatusEnum.ENABLE.getValue())
                .ne(User::getId, AdminUserConstant.ID)
                .orderByDesc(User::getId);
        return baseMapper.selectJoinPage(queryReq, UserInfoDto.class, queryWrapperE);
    }

    @Override
    public boolean hasPermission(Long userId, String permission){
        return baseMapper.selectUserCountByUserIdAndPermission(userId, permission) > 0;
    }
}
